home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 5817 / 5817.xpi / chrome / content / RowOperations.js < prev    next >
Text File  |  2010-02-11  |  26KB  |  756 lines

  1. Components.utils.import("resource://sqlitemanager/sqlite.js");
  2.  
  3. var RowOperations = {
  4.   mbConfirmationNeeded: false,
  5.  
  6.   maQueries: [],
  7.   maParamData: [],
  8.  
  9.   mNotifyMessages: ["Execution successful", "Execution failed"],
  10.   mAcceptAction: null,
  11.  
  12.   mIntervalID: null,
  13.  
  14.   //arrays with information for each field
  15.   aColumns: null,
  16.   aFieldValues: null,
  17.   aFieldTypes: null,
  18.   aDataTypes: null,
  19.   oldBlobs: null,
  20.   newBlobs: null,
  21.  
  22.   mRowId: null, //for update, delete and duplicate
  23.   sCurrentTable: null,
  24.   sObject: null,
  25.   sOperation: null,
  26.  
  27.   aOps: [
  28.       ["=", "=", ""],
  29.       ["!=", "!=", ""],
  30.       ["<", "<", ""],
  31.       ["<=", "<=", ""],
  32.       [">", ">", ""],
  33.       [">=", ">=", ""],
  34.       ["contains", 'like "%', '%"'],
  35.       ["begins with", 'like "', '%"'],
  36.       ["ends with", 'like "%', '"'],
  37.       ["IS NULL", "", ""],
  38.       ["IS NOT NULL", "", ""]
  39.     ],
  40.  
  41.   loadDialog: function () {
  42.     Database = window.arguments[0];
  43.     this.sCurrentTable = window.arguments[1];
  44.     this.sOperation = window.arguments[2];
  45.     this.mRowId = window.arguments[3];
  46.  
  47.     this.mbConfirmationNeeded = sm_prefsBranch.getBoolPref("confirm.records");
  48.  
  49.     switch(this.sOperation) {
  50.       case "insert":
  51.       case "duplicate":
  52.         document.title = sm_getLStr("rowOp.insert.title");
  53.         this.mAcceptAction = "doOKInsert";
  54.         this.setAcceptAction(this.mAcceptAction);
  55.         this.mNotifyMessages = [sm_getLStr("rowOp.insertSuccess.msg"), sm_getLStr("rowOp.insertFailure.msg")];
  56.         break;
  57.       case "update":
  58.         document.title = sm_getLStr("rowOp.update.title");
  59.         this.mAcceptAction = "doOKUpdate";
  60.         this.setAcceptAction(this.mAcceptAction);
  61.         this.mNotifyMessages = [sm_getLStr("rowOp.updateSuccess.msg"), sm_getLStr("rowOp.updateFailure.msg")];
  62.         break;
  63.       case "delete":
  64.         document.title = sm_getLStr("rowOp.delete.title");
  65.         this.mAcceptAction = "doOKDelete";
  66.         this.setAcceptAction(this.mAcceptAction);
  67.         break;
  68.       case "search":
  69.         document.title = sm_getLStr("rowOp.search.title") + this.sCurrentTable;
  70.         this.setAcceptAction("doOKSearch");
  71.         break;
  72.       case "search-view":
  73.         document.title = sm_getLStr("rowOp.searchView.title") + this.sCurrentTable;
  74.         this.setAcceptAction("doOKSearch");
  75.         this.loadForViewRecord(this.sCurrentTable, window.arguments[3]);
  76.         window.sizeToContent();
  77.         return;
  78.     }
  79.  
  80.     this.loadForTableRecord();
  81.     this.loadTableNames();
  82.     window.sizeToContent();
  83.   },
  84.  
  85.   setAcceptAction: function(sFunctionName) {
  86.     var dlg = $$("dialog-table-operations");
  87.     dlg.setAttribute("ondialogaccept",
  88.         "return RowOperations." + sFunctionName + "();");
  89.   },
  90.  
  91.   setCancelAction: function(sFunctionName) {
  92.     var dlg = $$("dialog-table-operations");
  93.     dlg.setAttribute("ondialogcancel",
  94.         "return RowOperations." + sFunctionName + "();");
  95.   },
  96.  
  97.   loadTableNames: function() {
  98.     this.sObject = "TABLE";
  99.     var listbox = $$("tablenames");
  100.  
  101.     var aNormTableNames = Database.getObjectList("table", "");
  102.     var aTempTableNames = [];
  103.     var aTableNames = aNormTableNames.concat(aTempTableNames);
  104.     PopulateDropDownItems(aTableNames, listbox, this.sCurrentTable);
  105.   },
  106.  
  107.   selectTable: function(sID) {
  108.     var sTable = $$(sID).value;
  109.     //to do, if the table dropdown is enabled
  110.   },
  111.  
  112.   doOK: function() {
  113.   },
  114.  
  115.   onSelectOperator: function(selectedOp, sFieldName) {
  116.     var ctrl = "ctrl-tb-" + sFieldName;
  117.     var node = $$(ctrl);
  118.     switch (this.aOps[selectedOp][0]) {
  119.       case "IS NULL":
  120.       case "IS NOT NULL":
  121.         node.disabled = true;
  122.         break;
  123.       default:
  124.         node.disabled = false;
  125.     }
  126.   },
  127.  
  128.   loadForTableRecord: function() {
  129.     $$("tablenames").setAttribute("disabled", true);
  130.     var sTableName = this.sCurrentTable;
  131.  
  132.     var cols = Database.getTableInfo(sTableName, "");
  133.  
  134.     this.aColumns = cols;
  135.     this.aFieldValues = [];
  136.     this.aFieldTypes = [];
  137.     this.aDataTypes = [];
  138.     this.oldBlobs = [];
  139.     this.newBlobs = [];
  140.  
  141.     for(var i = 0; i < cols.length; i++) {
  142.       this.aFieldValues.push("");
  143.       this.aDataTypes.push(3);
  144.       this.aFieldTypes.push(cols[i].type);
  145.  
  146.       this.oldBlobs.push(null);
  147.       this.newBlobs.push(null);
  148.     }
  149.  
  150.     if(this.sOperation == "update" || this.sOperation == "delete" || this.sOperation == "duplicate") {
  151.       var sql = "SELECT * FROM " + Database.getPrefixedName(sTableName, "") + " WHERE " + this.mRowId;
  152.       Database.selectQuery(sql);
  153.       var row = Database.getRecords()[0];
  154.       var cols = Database.getColumns();
  155.       var rowTypes = Database.getRecordTypes()[0];
  156.       for (var j = 0; j < this.aColumns.length; j++) {
  157.         for (var k = 0; k < cols.length; k++) {
  158.           if (cols[k][0] == this.aColumns[j].name) {
  159.             this.aDataTypes[j] = rowTypes[k];
  160.             this.aFieldValues[j] = row[k];
  161.           }
  162.         }
  163.         //for blobs, do the following
  164.         if (this.aDataTypes[j] == 4) {
  165.           var data = Database.selectBlob(this.sCurrentTable, this.aColumns[j].name, this.mRowId);
  166.           this.oldBlobs[j] = data;
  167.         }
  168.       }
  169.     }
  170.  
  171.     var grbox = $$("columnEntryFields");
  172.     SmGlobals.$empty(grbox);
  173.     var cap = document.createElement("caption");
  174.     cap.setAttribute("label", sm_getLStr("rowOp.enterFieldValues"));
  175.     grbox.appendChild(cap);
  176.  
  177.     for(var i = 0; i < this.aColumns.length; i++) {
  178.       var hbox = document.createElement("hbox");
  179.       hbox.setAttribute("flex", "0");
  180.       hbox.setAttribute("style", "margin:2px 3px 2px 3px");
  181.  
  182.       var lbl = document.createElement("label");
  183.       var lblVal = (i+1) + ". " + this.aColumns[i].name;
  184.       if(this.aFieldTypes[i].length > 0)
  185.         lblVal += " ( " + this.aFieldTypes[i] + " )";
  186.       lbl.setAttribute("value", lblVal);
  187.       lbl.setAttribute("style", "padding-top:5px;width:25ex");
  188.       if (i < 9)
  189.         lbl.setAttribute("accesskey", (i+1));
  190.       lbl.setAttribute("control", "ctrl-tb-" + i);
  191.       hbox.appendChild(lbl);
  192.  
  193.       var spacer = document.createElement("spacer");
  194.       spacer.flex = "1";
  195.       hbox.appendChild(spacer);
  196.  
  197.       if(this.sOperation == "search") {
  198.         var vb = this.getSearchMenuList(this.aColumns[i].name);
  199.         hbox.appendChild(vb);
  200.       }
  201.  
  202.       var inp1 = this.getInputField(i);
  203.       hbox.appendChild(inp1);
  204.  
  205.       var vb = this.getInputToggleImage(i, this.sOperation);
  206.       hbox.appendChild(vb);
  207.  
  208.       grbox.appendChild(hbox);
  209.     }
  210.     if (this.sOperation == "insert")
  211.       this.setInsertValues(true);
  212.  
  213.     window.sizeToContent();
  214.   },
  215.  
  216.   saveBlob: function(iIndex) {
  217.     if(this.sOperation != "update")
  218.       return false;
  219.  
  220.     const nsIFilePicker = Ci.nsIFilePicker;
  221.  
  222.     var fp = Cc["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
  223.     fp.init(window, sm_getLStr("rowOp.saveBlob.fp.title"), nsIFilePicker.modeSave);
  224.     fp.appendFilters(nsIFilePicker.filterAll);
  225.  
  226.     var rv = fp.show();
  227.     if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
  228.       var data = this.oldBlobs[iIndex];
  229.  
  230.       if(data.length == 0) //nothing to write
  231.         return false;
  232.  
  233.       var file = fp.file;
  234.       // Get the path as string. Note that you usually won't
  235.       // need to work with the string paths.
  236.       var path = fp.file.path;
  237.  
  238.       // file is nsIFile, data is a string
  239.       var foStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
  240.  
  241.       // use 0x02 | 0x10 to open file for appending.
  242.       foStream.init(file, 0x02 | 0x08 | 0x20, 0666, 0);
  243.       // write, create, truncate
  244.       // In a c file operation, we have no need to set file mode with or operation,
  245.       // directly using "r" or "w" usually.
  246.  
  247.       var bostream = Cc['@mozilla.org/binaryoutputstream;1'].createInstance(Ci.nsIBinaryOutputStream);
  248.       bostream.setOutputStream(foStream);
  249.       bostream.writeByteArray(data, data.length);
  250.  
  251.       bostream.close();
  252.       foStream.close();
  253.     }
  254.   },
  255.  
  256.   addBlob: function(iIndex) {
  257.     const nsIFilePicker = Ci.nsIFilePicker;
  258.  
  259.     var fp = Cc["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
  260.     fp.init(window, sm_getLStr("rowOp.addBlob.fp.title"), nsIFilePicker.modeOpen);
  261.     fp.appendFilters(nsIFilePicker.filterAll);
  262.  
  263.     var rv = fp.show();
  264.     if (rv == nsIFilePicker.returnOK) {
  265.       var fistream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
  266.       var bininput = Cc['@mozilla.org/binaryinputstream;1'].createInstance(Ci.nsIBinaryInputStream);
  267.  
  268.       var mimeservice = Cc['@mozilla.org/mime;1'].createInstance(Ci.nsIMIMEService);
  269.  
  270. //      var type = mimeservice.getTypeFromFile(fp.file);
  271. //      if(!type)
  272. //        type = "application/octet-stream";
  273.  
  274.       fistream.init(fp.file, 0x01, 0,5);
  275.       bininput.setInputStream(fistream);
  276.       var fileCounts = fistream.available();
  277.       var fileContents = bininput.readByteArray(fileCounts);
  278.       bininput.close();
  279.       fistream.close();
  280.  
  281.       this.newBlobs[iIndex] = fileContents;
  282.  
  283.       var ctrltb = $$("ctrl-tb-" + iIndex);
  284.       var val = sm_prefsBranch.getCharPref("textForBlob");
  285.       if (sm_prefsBranch.getBoolPref("showBlobSize"))
  286.         val += sm_getLFStr("rowOp.addBlob.showBlobSize", [fileCounts],1);
  287.  
  288.       ctrltb.setAttribute("value",val);
  289.       ctrltb.setAttribute("fieldtype","4");
  290.       ctrltb.setAttribute("disabled","true");
  291.  
  292.       var imgRemove = $$("img-removeBlob-" + iIndex);
  293.       imgRemove.setAttribute("hidden","false");
  294.     }
  295.   },
  296.  
  297.   removeBlob: function(iIndex) {
  298.     var ctrltb = $$("ctrl-tb-" + iIndex);
  299.     ctrltb.setAttribute("value","");
  300.     ctrltb.setAttribute("fieldtype","3");
  301.     ctrltb.removeAttribute("disabled");
  302.  
  303.     var imgSave = $$("img-saveBlob-" + iIndex);
  304.     imgSave.setAttribute("hidden","true");
  305.  
  306.     var imgRemove = $$("img-removeBlob-" + iIndex);
  307.     imgRemove.setAttribute("hidden","true");
  308.   },
  309.  
  310.   getSearchMenuList: function(sField) {
  311.     var ml = document.createElement("menulist");
  312.     ml.setAttribute("id", "op-" + sField);
  313.     ml.setAttribute("sizetopopup", "always");
  314.     ml.setAttribute("style", "max-width: 25ex");
  315.     ml.setAttribute("oncommand", "RowOperations.onSelectOperator(this.value, '" +  sField + "')");
  316.  
  317.     var mp = document.createElement("menupopup");
  318.  
  319.     for(var iOp = 0; iOp < this.aOps.length; iOp++) {
  320.       var mi = document.createElement("menuitem");
  321.       mi.setAttribute("label", this.aOps[iOp][0]);
  322.       mi.setAttribute("value", iOp);
  323.       if (iOp == 0)
  324.         mi.setAttribute("selected", "true");
  325.       mp.appendChild(mi);
  326.     }
  327.     ml.appendChild(mp);
  328.     var vb = document.createElement("vbox");
  329.     vb.appendChild(ml);
  330.     return vb;
  331.   },
  332.  
  333.   getInputToggleImage: function(iIndex, sOperation) {
  334.     var iType = 3;
  335.     if (this.aDataTypes != null)
  336.       iType = this.aDataTypes[iIndex];
  337.  
  338.     var hb = document.createElement("hbox");
  339.     var vb = document.createElement("vbox");
  340.     var img = document.createElement("image");
  341.     img.setAttribute("id", "img-" + iIndex);
  342.     img.setAttribute("src", "chrome://sqlitemanager/skin/images/expand.png");
  343.     img.setAttribute("style", "margin-top:5px;");
  344.     img.setAttribute("tooltiptext", sm_getLStr("rowOp.tooltip.expandInput"));
  345.     img.setAttribute("onclick", 'RowOperations.collapseInputField("' + iIndex + '")');
  346.     vb.appendChild(img);
  347.     hb.appendChild(vb);
  348.  
  349.     if (sOperation == "update" || sOperation == "insert" || sOperation == "duplicate") {
  350.       var vb1 = document.createElement('vbox');
  351.       var img1 = document.createElement('image');
  352.       img1.setAttribute('id', 'img-addBlob-' + iIndex);
  353.       img1.setAttribute('src', 'chrome://sqlitemanager/skin/images/attachBlob.gif');
  354.       img1.setAttribute("style", "margin-top:5px;");
  355.       img1.setAttribute("tooltiptext", sm_getLStr("rowOp.tooltip.addBlob"));
  356.       img1.setAttribute("onclick", 'RowOperations.addBlob(' + iIndex + ')');
  357.       vb1.appendChild(img1);
  358.       hb.appendChild(vb1);
  359.  
  360.       var vb2 = document.createElement('vbox');
  361.       var img2 = document.createElement('image');
  362.       img2.setAttribute('id', 'img-saveBlob-' + iIndex);
  363.       img2.setAttribute('src', 'chrome://sqlitemanager/skin/images/saveBlob.png');
  364.       img2.setAttribute('style', 'margin-top:5px;');
  365.       img2.setAttribute("tooltiptext", sm_getLStr("rowOp.tooltip.saveBlob"));
  366.       img2.setAttribute('onclick', 'RowOperations.saveBlob(' + iIndex + ')');
  367.        img2.setAttribute('hidden', 'true');
  368.       if (iType == 4)
  369.         img2.setAttribute('hidden', 'false');
  370.       vb2.appendChild(img2);
  371.       hb.appendChild(vb2);
  372.  
  373.       var vb3 = document.createElement('vbox');
  374.       var img3 = document.createElement('image');
  375.       img3.setAttribute('id', 'img-removeBlob-' + iIndex);
  376.       img3.setAttribute('src', 'chrome://sqlitemanager/skin/images/delete_red.gif');
  377.       img3.setAttribute('style', 'margin-top:5px;');
  378.       img3.setAttribute("tooltiptext", sm_getLStr("rowOp.tooltip.deleteBlob"));
  379.       img3.setAttribute('onclick', 'RowOperations.removeBlob(' + iIndex + ')');
  380.        img3.setAttribute('hidden', 'true');
  381.       if (iType == 4)
  382.         img3.setAttribute('hidden', 'false');
  383.       vb3.appendChild(img3);
  384.       hb.appendChild(vb3);
  385.     }
  386.     return hb;
  387.   },
  388.  
  389.   getTextBoxHeight: function() {
  390.     //show the reference textbox, get the height and hide it
  391.     //needed because multiline is taller than normal textbox even when rows=1
  392.     var oRef = $$("reference");
  393.     oRef.hidden = false;
  394.     var iHeight = oRef.boxObject.height;
  395.     oRef.hidden = true;
  396.     return iHeight;
  397.   },
  398.  
  399.   getInputField: function(iIndex) {
  400.     var sField = this.aColumns[iIndex].name;
  401.     var sValue = "", iType = 3;
  402.     if (this.aFieldValues != null)
  403.       sValue = this.aFieldValues[iIndex];
  404.     if (this.aDataTypes != null)
  405.       iType = this.aDataTypes[iIndex];
  406.  
  407.     var inp1 = document.createElement("textbox");
  408.     inp1.setAttribute("id", "ctrl-tb-" + iIndex);
  409.     inp1.setAttribute("flex", "30");
  410.     inp1.setAttribute("value", sValue);
  411.  
  412. //    inp1.setAttribute("onkeypress", "adjustTextboxRows(this, 1, 10)");
  413.  
  414.     inp1.setAttribute("multiline", "true");
  415.     inp1.setAttribute("rows", "1");
  416.     if (iType == 4)
  417.       inp1.setAttribute("disabled", "true");
  418.     //following attributes are not in xul
  419.     inp1.setAttribute("originalvalue", sValue);
  420.     inp1.setAttribute("fieldtype", iType);
  421.  
  422.     var iHeight = this.getTextBoxHeight();
  423.     inp1.setAttribute("height", iHeight);
  424.  
  425.     return inp1;
  426.   },
  427.  
  428.   setInsertValues: function(bForceDefault) {
  429.     //Issue #169
  430.     if (!bForceDefault) {
  431.       var sInsertFieldStatus = sm_prefsBranch.getCharPref("whenInsertingShow");
  432.       if (sInsertFieldStatus != "default")
  433.         return false;
  434.     }
  435.  
  436.     for(var i = 0; i < this.aColumns.length; i++) {
  437.       var inptb = $$("ctrl-tb-" + i);
  438.       //use col_default_val attr to handle not-so-simple default values like 20-3, etc.
  439.       var sVal = SQLiteFn.defaultValToInsertValue(this.aColumns[i].dflt_value);
  440.       //Issue #391: using ".value =" here followed by setAttribute("value",val) fails to display val 
  441.       //inptb.value = sVal;
  442.       inptb.setAttribute('value', sVal);
  443.       inptb.setAttribute('col_default_val', sVal);
  444.     }
  445.   },
  446.  
  447.   typeConstant: function(sConstant) {
  448.     var focused = document.commandDispatcher.focusedElement;
  449.     if (focused.tagName == "html:textarea")
  450.       focused.value = sConstant;
  451.   },
  452.  
  453.   collapseInputField: function(id) {
  454.     var inptb = $$("ctrl-tb-" + id);
  455.     var iLines = inptb.getAttribute("rows");
  456.     var bMultiline = inptb.hasAttribute("multiline");
  457.     var iMinRows = 1, iMaxRows = 10;
  458.  
  459.     var img = $$("img-" + id);
  460.     if (iLines == 1) {
  461.       inptb.removeAttribute("height");
  462.       adjustTextboxRows(inptb, iMinRows, iMaxRows);
  463.       img.setAttribute('src', 'chrome://sqlitemanager/skin/images/collapse.png');
  464.       img.setAttribute("tooltiptext", sm_getLStr("rowOp.tooltip.collapseInput"));
  465.     }
  466.     else {
  467.       var iHeight = this.getTextBoxHeight();
  468.       inptb.setAttribute("height", iHeight);
  469.       inptb.setAttribute("rows", 1);
  470.       img.setAttribute('src', 'chrome://sqlitemanager/skin/images/expand.png');
  471.       img.setAttribute("tooltiptext", sm_getLStr("rowOp.tooltip.expandInput"));
  472.     }
  473.   },
  474.  
  475.   loadForViewRecord: function(sViewName, aViewColInfo) {
  476.     $$("tablenames").hidden = true;
  477.     $$("label-name").value = sm_getLStr("rowOp.viewName") + sViewName;
  478.  
  479.     var aNames = aViewColInfo[0];
  480.     var aTypes = aViewColInfo[1];
  481.  
  482.     var grbox = $$("columnEntryFields");
  483.     SmGlobals.$empty(grbox);
  484.     var cap = document.createElement("caption");
  485.     cap.setAttribute("label", sm_getLStr("rowOp.enterFieldValues"));
  486.     grbox.appendChild(cap);
  487.  
  488.     this.aColumns = [];
  489.     for(var i = 0; i < aNames.length; i++) {
  490.       var oneCol = {};
  491.       oneCol.name = aNames[i];
  492.       this.aColumns.push(oneCol);
  493.  
  494.       var hbox = document.createElement("hbox");
  495.       hbox.setAttribute("flex", "1");
  496.       hbox.setAttribute("style", "margin:2px 3px 2px 3px");
  497.  
  498.       var lbl = document.createElement("label");
  499.       var lblVal = (i+1) + ". " + aNames[i];
  500.       lblVal += " ( " + aTypes[i] + " )";
  501.       lbl.setAttribute("value", lblVal);
  502.       lbl.setAttribute("style", "padding-top:5px;width:25ex");
  503.       if (i < 9)
  504.         lbl.setAttribute("accesskey", (i+1));
  505.       lbl.setAttribute("control", "ctrl-tb-" + i);
  506.       hbox.appendChild(lbl);
  507.  
  508.       var spacer = document.createElement("spacer");
  509.       spacer.flex = "1";
  510.       hbox.appendChild(spacer);
  511.  
  512.       var vb = this.getSearchMenuList(aNames[i]);
  513.       hbox.appendChild(vb);
  514.  
  515.       var inp = this.getInputField(i);
  516.       hbox.appendChild(inp);
  517.  
  518.       var vb = this.getInputToggleImage(i);
  519.       hbox.appendChild(vb);
  520.  
  521.       grbox.appendChild(hbox);
  522.     }
  523.   },
  524.  
  525.   doOKInsert: function() {
  526.     var colPK = null;
  527.     var rowidcol = Database.getTableRowidCol(this.sCurrentTable);
  528.     if (rowidcol["name"] != "rowid")
  529.       colPK = rowidcol["name"];
  530.  
  531.     var inpval, fld;
  532.     var aCols = [];
  533.     var aVals = [];
  534.  
  535.     var iParamCounter = 1;
  536.     var aParamData = [];
  537.     for(var i = 0; i < this.aColumns.length; i++) {
  538.       var ctrltb = $$("ctrl-tb-" + i);
  539.       inpval = ctrltb.value;
  540.  
  541.       //this is to allow autoincrement of primary key columns and accept default values where available
  542.       //also, use col_default_val attr to correctly interpret the not-so-simple default values (e.g. 20 - 3)
  543.       if (this.aColumns[i].dflt_value != null || colPK == this.aColumns[i].name)
  544.         if(inpval.toUpperCase() == SQLiteFn.getStrForNull() || inpval.length == 0 || inpval == ctrltb.getAttribute('col_default_val'))
  545.           continue;
  546.  
  547.       //when no input, omit column from insert unless null not allowed
  548.       if (inpval.length == 0 && this.aColumns[i].notnull == 0)
  549.         continue;
  550.  
  551.       var iType = ctrltb.getAttribute("fieldtype");
  552.       if (iType == 4 && this.newBlobs[i] == null)
  553.         continue;
  554.  
  555.       inpval = SQLiteFn.makeSqlValue(inpval);
  556.       fld = SQLiteFn.quoteIdentifier(this.aColumns[i].name);
  557.  
  558.       if (iType == 4) {
  559.         inpval = "?" + iParamCounter;
  560.         aParamData.push([(iParamCounter-1), this.newBlobs[i], "blob"]);
  561.         iParamCounter++;
  562.       }
  563.  
  564.       aCols.push(fld);
  565.       aVals.push(inpval);
  566.     } 
  567.     var cols = "(" + aCols.toString() + ")";
  568.     var vals = "(" + aVals.toString() + ")";
  569.  
  570.     this.maQueries = ["INSERT INTO " + Database.getPrefixedName(this.sCurrentTable, "") + " " + cols + " VALUES " + vals];
  571.     this.maParamData = aParamData
  572.     if (this.mbConfirmationNeeded)
  573.       this.seekConfirmation();
  574.     else
  575.       this.doOKConfirm();
  576.     return false;
  577.   },
  578.  
  579.   notify: function(sMessage, sType) {
  580.     sm_notify("boxNotify", sMessage, sType);
  581.   },
  582.  
  583.   doOKUpdate: function() {
  584.     var inpval, fld, inpOriginalVal, iType;
  585.     var cols = "";
  586.     var vals = "";
  587.     var aParamData = [];
  588.     var iParamCounter = 1;
  589.     for(var i = 0; i < this.aColumns.length; i++) {
  590.       var ctrltb = $$("ctrl-tb-" + i);
  591.       inpval = ctrltb.value;
  592.       inpOriginalVal = ctrltb.getAttribute("originalvalue");
  593.       inpval = SQLiteFn.makeSqlValue(inpval);
  594.       inpOriginalVal = SQLiteFn.makeSqlValue(inpOriginalVal);
  595.  
  596.       iType = ctrltb.getAttribute("fieldtype");
  597.       if (iType == 4 && this.newBlobs[i] == null)
  598.         continue;
  599.  
  600.       if (inpOriginalVal == inpval)
  601.         continue;
  602.  
  603.       if (iType == 4) {
  604.         inpval = "?" + iParamCounter;
  605.         aParamData.push([(iParamCounter-1), this.newBlobs[i], "blob"]);
  606.         iParamCounter++;
  607.       }
  608.  
  609.       fld = SQLiteFn.quoteIdentifier(this.aColumns[i].name);
  610.       if(cols != "") {
  611.         fld = ", " + fld;
  612.       }
  613.       cols += fld + " = " + inpval;
  614.     } 
  615.  
  616.     if (cols == "") {
  617.       alert(sm_getLStr("rowOp.noChanges"));
  618.       return false;
  619.     }
  620.  
  621.     this.maQueries = ["UPDATE " + Database.getPrefixedName(this.sCurrentTable, "") + " SET " + cols + " WHERE " + this.mRowId];
  622.     this.maParamData = aParamData
  623.     if (this.mbConfirmationNeeded)
  624.       this.seekConfirmation();
  625.     else
  626.       this.doOKConfirm();
  627.     return false;
  628.   },
  629.  
  630. //required in case delete option is added to the edit record dialog
  631.   doOKDelete: function() {
  632.     this.maQueries = ["DELETE FROM " +
  633.           Database.getPrefixedName(this.sCurrentTable, "")+ " WHERE " + this.mRowId];
  634.     this.maParamData = null;
  635.     if (this.mbConfirmationNeeded)
  636.       this.seekConfirmation();
  637.     else
  638.       this.doOKConfirm();
  639.     return false;
  640.   },
  641.  
  642.   //used for searching within table/view
  643.   doOKSearch: function() {
  644.     var inpval, opval, fld;
  645.     var where = "";
  646.     for(var i = 0; i < this.aColumns.length; i++) {
  647.       var ctrltb = $$("ctrl-tb-" + i);
  648.       inpval = ctrltb.value;
  649.       if (inpval.length == 0)
  650.         continue;
  651.       opval = $$("op-" + this.aColumns[i].name).value;
  652. //      if (this.aOps[opval][0] == g_strIgnore)
  653. //        continue;
  654.  
  655.       switch (this.aOps[opval][0]) {
  656.         case "IS NULL":
  657.           inpval = " ISNULL ";
  658.           break;
  659.         case "IS NOT NULL":
  660.           inpval = " NOTNULL ";
  661.           break;
  662.         default:
  663.           if (this.aOps[opval][2] != "") {
  664.             inpval = this.aOps[opval][1] + inpval + this.aOps[opval][2];
  665.           }
  666.           else {//figure out whether value is string/constant
  667.             inpval = this.aOps[opval][1] + SQLiteFn.makeSqlValue(inpval);
  668.           }
  669.           break;
  670.       }
  671.       inpval = SQLiteFn.quoteIdentifier(this.aColumns[i].name) + " " + inpval;
  672.  
  673.       if(where.length > 0)
  674.         inpval = " AND " + inpval;
  675.  
  676.       where += inpval;
  677.     }
  678.     var extracol = "";
  679.     if (this.sOperation == "search") {  //do this for table, not for view
  680.       var rowidcol = Database.getTableRowidCol(this.sCurrentTable);
  681.       if (rowidcol["name"] == "rowid")
  682.         extracol = " rowid, ";
  683.     }
  684.     if(where.length > 0)
  685.       where = " WHERE " + where;
  686.  
  687.     var answer = true;
  688.     if(answer) {
  689.       //the order in which the following are set is important
  690.       //Issue #285: set unicode string
  691.       sm_setUnicodePref("searchCriteria", where);
  692.       //the value of searchToggler should toggle for change event to fire.
  693.       var bTemp = sm_prefsBranch.getBoolPref("searchToggler");
  694.       sm_prefsBranch.setBoolPref("searchToggler", !bTemp);
  695.     }
  696.     //return false so that window stays there for more queries
  697.     //the user must cross, escape or cancel to exit
  698.     //return false; //commented due to Issue #32
  699.   },
  700.  
  701.   doCancel: function() {
  702.       return true;
  703.   },
  704.  
  705.   doOKConfirm: function() {
  706.     this.changeState(0);
  707.     var bRet = Database.executeWithoutConfirm(this.maQueries, this.maParamData);
  708.     if (bRet) {
  709.       this.notify(this.mNotifyMessages[0], "info");
  710.  
  711.       //do the following to trigger SQLiteManager.loadTabBrowse();
  712.       sm_setUnicodePref("searchCriteria", "nocriteria");
  713.       //the value of searchToggler should toggle for loadTabBrowse() to be called.
  714.       var bTemp = sm_prefsBranch.getBoolPref("searchToggler");
  715.       sm_prefsBranch.setBoolPref("searchToggler", !bTemp);
  716.     }
  717.     else {
  718.       this.notify(this.mNotifyMessages[1], "warning");
  719.     }
  720.  
  721.     if (this.mAcceptAction == "doOKInsert") {
  722.       this.setInsertValues(false);
  723.       $$("ctrl-tb-0").focus();
  724.     }
  725.     if (this.mAcceptAction == "doOKUpdate") {
  726.       //TODO: reset values so that no further change means no more update
  727.     }
  728.     return false;
  729.   },
  730.  
  731.   doCancelConfirm: function() {
  732.     this.changeState(0);
  733.     return false;
  734.   },
  735.  
  736.   changeState: function(iNewState) {
  737.     $$("deck-rowedit").selectedIndex = iNewState;
  738.     if (iNewState == 0) {
  739.       this.setAcceptAction(this.mAcceptAction);  
  740.       this.setCancelAction("doCancel");  
  741.     }
  742.     if (iNewState == 1) {
  743.       this.setAcceptAction("doOKConfirm");  
  744.       this.setCancelAction("doCancelConfirm");  
  745.     }
  746.   },
  747.  
  748.   seekConfirmation: function() {
  749.     var ask = sm_getLStr("rowOp.confirmation");
  750.     var txt = ask + "\n\n" + this.maQueries.join("\n");
  751. //    $$("tbMessage").value = txt;
  752.     $$("tbMessage").textContent = txt;
  753.     this.changeState(1);
  754.   }
  755. };
  756.